//获取cookie数据
function getCookie(cookieName) {
    const strCookie = document.cookie;
    const cookieList = strCookie.split(';');
    for (let i = 0; i < cookieList.length; i++) {
        const arr = cookieList[i].split('=');
        if (cookieName === arr[0].trim()) {
            return arr[1];
        }
    }
    return '';
}
function str2UTF8(str){
    const bytes = [];
    let len, c;
    len = str.length;
    for(let i = 0; i < len; i++){
        c = str.charCodeAt(i);
        if(c >= 0x010000 && c <= 0x10FFFF){
            bytes.push(((c >> 18) & 0x07) | 0xF0);
            bytes.push(((c >> 12) & 0x3F) | 0x80);
            bytes.push(((c >> 6) & 0x3F) | 0x80);
            bytes.push((c & 0x3F) | 0x80);
        }else if(c >= 0x000800 && c <= 0x00FFFF){
            bytes.push(((c >> 12) & 0x0F) | 0xE0);
            bytes.push(((c >> 6) & 0x3F) | 0x80);
            bytes.push((c & 0x3F) | 0x80);
        }else if(c >= 0x000080 && c <= 0x0007FF){
            bytes.push(((c >> 6) & 0x1F) | 0xC0);
            bytes.push((c & 0x3F) | 0x80);
        }else{
            bytes.push(c & 0xFF);
        }
    }
    return bytes;
}

let websocket = null;
const processingResMap = new Map();
const MpcUtil = {
    /**
     * 连接服务
     * @param host
     * @param onopen
     * @param onmessage
     */
    connect: function (host, onopen, onmessage) {
        websocket = new WebSocket(host);
        websocket.onopen = () => {
            console.log("message plus core 连接成功！");
            setInterval(()=>{
                this.heartbeat();
            },20000);
            websocket.onmessage = (res) => {
                const message = JSON.parse(res.data);
                // console.log("有新消息！");
                const id = message.id;
                if (id!==undefined) {
                    const processingRes = processingResMap.get(id);
                    if (processingRes!==undefined) {
                        processingRes(message);
                    }
                }
                onmessage(message);
            };
            // 发送心跳请求
            this.heartbeat();
            if (onopen) onopen();
        }
    },
    processing: function(processingRes) {
        const id = crypto.randomUUID();
        if (processingRes!==undefined) {
            processingResMap.set(id, processingRes)
        }
        return id;
    },
    /**
     * 向服务器发生心跳请求
     */
    heartbeat: function () {
        const o = {
            id: Date.now().toString(),
            type: 0,
            headers: {
                'token': getCookie('satoken')
            }
        };
        websocket.send(this.getBuf(o));
    },
    /**
     * 发送自定义请求
     */
    send: function (o) {
        o.id = Date.now().toString();
        o.headers = {
            'token': getCookie('satoken')
        };
        websocket.send(this.getBuf(o));
        return o;
    },
    /**
     * 发送路径请求
     * @param path 路径
     * @param args 参数
     * @param processingRes 响应处理方法
     */
    sendPath: function (path, args, processingRes) {
        const id = this.processing(processingRes);
        const o = {
            id: id,
            type: 3,
            headers: {
                'token': getCookie('satoken')
            },
            path: path,
            args: args
        };
        websocket.send(this.getBuf(o));
    },
    /**
     * 发送聊天请求
     * @param toType 接收方类型
     * @param toId 接收方ID
     * @param content 内容
     */
    sendChat: function (toType, toId, content) {
        const o = {
            id: Date.now().toString(),
            type: 1,
            headers: {
                'token': getCookie('satoken')
            },
            toType: toType,
            toId: toId,
            content: content
        };
        websocket.send(this.getBuf(o));
        return o;
    },
    sendAudio: function (toType, toId, chunk) {
        const reader = new FileReader();
        reader.onload = ()=> {
            let audioBuffer = reader.result;
            console.log(audioBuffer);
            const arr = this.getAudioBuf({
                id: Date.now().toString(),
                type: 4,
                headers: {
                    'token': getCookie('satoken')
                },
                toType: toType,
                toId: toId
            }, audioBuffer);
            for (let a of arr) {
                websocket.send(a);
            }
        }
        reader.readAsArrayBuffer(chunk);
        return {
            id: Date.now().toString(),
            type: 4,
            headers: {
                'token': getCookie('satoken')
            },
            toType: toType,
            toId: toId
        };
    },
    sendPic: function (toType, toId, picBlob) {
        const reader = new FileReader();
        reader.onload = function()  {
            const arr = MpcUtil.getAudioBuf({
                id: Date.now().toString(),
                type: 5,
                headers: {
                    'token': getCookie('satoken')
                },
                toType: toType,
                toId: toId
            }, this.result);
            for (let a of arr) {
                websocket.send(a);
            }
        }
        reader.readAsArrayBuffer(picBlob);
        return {
            id: Date.now().toString(),
            type: 5,
            headers: {
                'token': getCookie('satoken')
            },
            toType: toType,
            toId: toId
        };
    },
    /**
     * 响应处理
     * @param func
     */
    responseHandler: function (func) {
        websocket.onmessage = func;
    },
    /**
     * 转换对象为buffer
     * @param o 对象
     * @returns {ArrayBuffer}
     */
    getBuf: function (o) {
        const jsonObject = JSON.stringify(o);
        // let bytes = Array.from(jsonObject, char => char.charCodeAt(0));
        let bytes = str2UTF8(jsonObject);
        const buffer = new ArrayBuffer(bytes.length + 7);
        const view = new DataView(buffer);
        // 请求版本
        view.setUint8(0, 1);
        // 请求类型
        view.setUint16(1, Number.parseInt(o.type));
        // 内容长度
        view.setInt32(3, bytes.length);
        // 请求内容
        for (const x in bytes) {
            view.setUint8(Number.parseInt(x) + 7, bytes[x]);
        }
        return buffer;
    },
    /**
     * 转换audio类的消息为buf
     * @param o
     * @param audioBuf
     * @returns {*[]}
     */
    getAudioBuf: function (o, audioBuf) {
        // 切片最大长度
        const sliceMaxLength = 60000;
        // 切片
        let arrayBuffer;
        // 切片数组
        const arr = [];
        // 音频长度
        const buf2 = new ArrayBuffer(4);
        const view = new DataView(buf2);
        view.setInt32(0, audioBuf.byteLength);
        // 大于6000，需要切片
        if (audioBuf.byteLength > sliceMaxLength) {
            const i = Math.ceil(audioBuf.byteLength / sliceMaxLength);
            o['sliceId'] = 1;
            o['sliceNum'] = i;
            for (let x = 0; x < i; ++x) {
                let index= x * sliceMaxLength;
                o['currentIndex'] = x + 1;
                const buf1 = this.getBuf(o);
                arrayBuffer = this.mergeArrayBuffers([buf1, buf2, audioBuf.slice(index, index + sliceMaxLength)]);
                arr.push(arrayBuffer);
            }
        } else {
            o['sliceNum'] = 1;
            o['currentIndex'] = 1;
            const buf1 = this.getBuf(o);
            arrayBuffer = this.mergeArrayBuffers([buf1, buf2, audioBuf]);
            arr.push(arrayBuffer);
        }

        return arr;
    },
    /**
     * 合并audio响应
     */
    byteBuf: null,
    mergeAudioResponse: function (response) {
        if (response.currentIndex < response.sliceNum) {
            const bytes = Array.from(Object.values(response.bytes), x => x);
            const arrayBuffer = new ArrayBuffer(bytes.length);
            const view = new DataView(arrayBuffer);
            for (const i in bytes) {
                view.setUint8(Number.parseInt(i), bytes[i]);
            }
            if (this.byteBuf === null) {
                this.byteBuf = arrayBuffer;
            } else {
                this.byteBuf = this.mergeArrayBuffers([this.byteBuf, arrayBuffer]);
            }
        } else {
            const bytes = Array.from(Object.values(response.bytes), x => x);
            const arrayBuffer = new ArrayBuffer(bytes.length);
            const view = new DataView(arrayBuffer);
            for (const i in bytes) {
                view.setUint8(Number.parseInt(i), bytes[i]);
            }
            if (this.byteBuf === null) {
                return arrayBuffer;
            } else {
                console.log("完成！")
                this.byteBuf = this.mergeArrayBuffers([this.byteBuf, arrayBuffer]);
                const buffer = this.byteBuf;
                this.byteBuf = null;
                return buffer;
            }
        }
    },
    /**
     * 合并ArrayBuffer
     */
    mergeArrayBuffers: function (arrayBuffers) {
        // 计算新的ArrayBuffer的总长度
        let totalLength = 0;
        for (const buffer of arrayBuffers) {
            totalLength += buffer.byteLength;
        }
        // 创建一个新的ArrayBuffer
        const mergedBuffer = new ArrayBuffer(totalLength);
        // 创建一个Uint8Array以便操作新的ArrayBuffer
        const uint8Array = new Uint8Array(mergedBuffer);
        let offset = 0;
        // 逐个复制ArrayBuffer到新的ArrayBuffer中
        for (const buffer of arrayBuffers) {
            const sourceArray = new Uint8Array(buffer);
            uint8Array.set(sourceArray, offset);
            offset += sourceArray.length;
        }
        return mergedBuffer;
    }
};

export default MpcUtil;
